package com.java.androidmarket.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.java.androidmarket.aspect.CheckUser;
import com.java.androidmarket.aspect.NoRepeatSubmit;
import com.java.androidmarket.dto.order.OrderDTO;
import com.java.androidmarket.dto.order.GetOrderDTO;
import com.java.androidmarket.entity.KillStock;
import com.java.androidmarket.entity.Order;
import com.java.androidmarket.entity.OrderGoods;
import com.java.androidmarket.entity.Result;
import com.java.androidmarket.service.*;
import com.java.androidmarket.utils.MD5Utils;
import com.java.androidmarket.utils.RedisUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * description:
 * author:张腾
 * date:2021-05-15
 */

@RestController
@CrossOrigin
@RequestMapping("order")
@Api(tags = "订单模块")
public class OrderController {

    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderGoodsService orderGoodsService;
    @Autowired
    private StockService stockService;
    @Autowired
    private CartService cartService;
    @Autowired
    private KillStockService killStockService;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private RedissonClient redissonClient;



    @PostMapping("add")
    @ApiOperation(value = "订单新增", notes = "用户提交订单信息")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "Order", name = "order", value = "订单信息"),
            @ApiImplicitParam(dataType = "List<OrderGoods>", name = "orderGoodsList", value = "该订单下购买的商品列表"),
            @ApiImplicitParam(dataType = "int", name = "state", value = "是否从购物车调用")
    })
    @Transactional
    @NoRepeatSubmit
    public Result addOrder(@RequestBody OrderDTO orderDTO) throws InterruptedException {

//        ObjectMapper mapper = new ObjectMapper();

        Order order = orderDTO.getOrder();
        List<OrderGoods> orderGoodsList = orderDTO.getOrderGoodsList();
//            Order order = mapper.convertValue(map.get("Order"), new TypeReference<Order>() {});
//            List<OrderGoods> orderGoodsList = mapper.convertValue(map.get("OrderGoods"),
//                    new TypeReference<List<OrderGoods>>() {});
//            Order order = JSON.parseObject(JSON.toJSONString(map.get("Order"))
//                                            , Order.class);
//            List<OrderGoods> orderGoodsList = JSON.parseObject(
//                    JSON.toJSONString(map.get("OrderGoods")), List.class);

        //校验库存
        ArrayList<Integer> list = new ArrayList<>();
        boolean flag = false;
        for (OrderGoods orderGoods : orderGoodsList) {
            if (!stockService.checkStock(orderGoods.getGoodsId(), orderGoods.getGoodsNum())) {
                System.out.println(orderGoods.getGoodsId() + "号商品库存不足");
                list.add(orderGoods.getGoodsId());
                flag = true;
            }
        }
        if (flag){
            return Result.error("-1","库存不足",list);
        }
        orderService.deleteRedis();

        //新增订单记录
        if (orderService.addOrder(order) > 0) {

            for (OrderGoods orderGoods : orderGoodsList) {
                //新增订单商品记录
                orderGoods.setOrderId(order.getOrderId());
                orderGoodsService.insert(orderGoods);

                //删除购物车对应商品
                if (orderDTO.getState() == 1) {
                    if (redisUtils.exists("Cart:" + order.getUserId())) {
                        redisUtils.del("Cart:" + order.getUserId());
                    }
                    cartService.deleteGoods(order.getUserId(), orderGoods.getGoodsId());
                }
            }

            //将订单插入redis，10分钟后超时为订单关闭
            redisUtils.set("OOTOrder:" + order.getOrderSn(), "YES", 2L, TimeUnit.MINUTES);
        }
//            for (int i = 0; i < orderGoodsList.size(); i++) {
//                OrderGoods orderGoods = JSON.parseObject(JSON.toJSONString(orderGoodsList.get(i)), OrderGoods.class);
//                System.out.println(orderGoods);
//            }


        return Result.success(order.getOrderSn());

    }

    @PostMapping("confirm")
    @ApiOperation(value = "确认购买", notes = "根据orderSn将订单状态修改为待评价")
    @ApiImplicitParam(dataType = "String", name = "orderSn", value = "订单编号")
    @Transactional
    public Result confirm(@RequestBody OrderDTO orderDTO){
        String orderSn = orderDTO.getOrderSn();

        Order order = new Order();
        order.setOrderSn(orderSn).setOrderStatus(1);
        //修改订单状态为待评价
        orderService.changeStatus(order);

        redisUtils.del("OOTOrder:"+orderSn);
        orderService.deleteRedis(orderSn);

        //修改库存表
        //修改商品销量
        int orderId = orderService.getOrderId(orderSn);
        List<OrderGoods> orderGoodsList = orderGoodsService.getOrderGoods(orderId);
        for (OrderGoods orderGoods : orderGoodsList) {
            stockService.lockTosSale(orderGoods);
            goodsService.dealCountChange(orderGoods.getGoodsId(),orderGoods.getGoodsNum());
        }

        return Result.success();
    }


    @GetMapping("getAll")
    @ApiOperation(value = "获取订单信息", notes = "获取用户所有订单信息")
    @ApiImplicitParam(dataType = "int", name = "userId", value = "用户ID")
    @CheckUser
    public Result getAllOrderGoods(int userId){

        String key = "AllOrder:"+userId;
        List<GetOrderDTO> orderList = new ArrayList<>();
        int total = 0;
        if (redisUtils.exists(key)){
            System.out.println("redis根据用户id查找所有订单");
            orderList = (List<GetOrderDTO>) redisUtils.hmGet(key,"OrderList");
            total = (int) redisUtils.hmGet(key,"Total");
        }else{
            System.out.println("数据库根据用户id查找所有订单");
            orderList = orderService.getAllOrder(userId);
            total = orderList.size();
            redisUtils.hmSet(key,"OrderList",orderList);
            redisUtils.hmSet(key,"Total",orderList.size());
        }

        return Result.success(orderList, total);
    }

    @GetMapping("getByOrderSn")
    @ApiOperation(value = "获取单个订单信息", notes = "根据订单编号获取订单信息")
    @ApiImplicitParam(dataType = "String", name = "orderSn", value = "订单编号")
    @CheckUser
    public Result getOneOrder(String orderSn){
        GetOrderDTO order = new GetOrderDTO();
        if (redisUtils.exists("OneOrder:"+orderSn)) {
            System.out.println("redis根据orderId查找单个订单");
            order = (GetOrderDTO) redisUtils.get("OneOrder:" + orderSn);
        } else {
            System.out.println("数据库根据orderId查找单个订单");
            order = orderService.getOneOrder(orderSn);
            redisUtils.set("OneOrder:"+orderSn,order);
        }

        return Result.success(order,1);
    }


    @GetMapping("getOrderByStatus")
    @ApiOperation(value = "根据订单状态获取订单信息", notes = "根据订单状态分类获取用户的订单信息")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "int", name = "userId", value = "用户ID"),
            @ApiImplicitParam(dataType = "int", name = "orderStatus", value = "订单状态")
    })
    @CheckUser
    public Result getOrderByStatus(int userId,int orderStatus){

        List<GetOrderDTO> orderList = new ArrayList<>();
        if (redisUtils.hmExist("StatusOrder:"+userId,String.valueOf(orderStatus))) {
            System.out.println("redis根据用户id查找订单分类");
            orderList = (List<GetOrderDTO>) redisUtils.hmGet("StatusOrder:"+userId,String.valueOf(orderStatus));
        }else{
            System.out.println("数据库根据用户id查找订单分类");
            orderList = orderService.getOrderByStatus(userId,orderStatus);
            redisUtils.hmSet("StatusOrder:"+userId,String.valueOf(orderStatus),orderList);
        }

        return Result.success(orderList, orderList.size());
    }


    @GetMapping("getOrderNum")
    @ApiOperation(value = "获取订单数量",notes = "获取待评价和待支付的订单的数量")
    @ApiImplicitParam(dataType = "int", name = "userId", value = "用户ID")
    public Result getOrderNum(int userId){
        List<Map<String,Integer>> orderNum = orderService.getOrderNum(userId);
        System.out.println("获取用户未评价未支付订单数量");
        return Result.success(orderNum);
    }


    @PostMapping("delete")
    @ApiOperation(value = "删除订单", notes = "根据订单编号删除订单")
    @ApiImplicitParam(dataType = "String", name = "orderSn", value = "订单编号")
    @Transactional
    public Result deleteOrder(@RequestBody OrderDTO orderDTO){
        String orderSn = orderDTO.getOrderSn();

        orderService.deleteRedis(orderSn);

        int orderId = orderService.getOrderId(orderSn);
        orderService.deleteOrder(orderSn);
        orderGoodsService.deleteOrderGoods(orderId);

        return Result.success();
    }


    @PostMapping("cancel")
    @ApiOperation(value = "取消订单", notes = "根据订单编号将待支付的订单修改为已关闭")
    @ApiImplicitParam(dataType = "String", name = "orderSn", value = "订单编号")
    public Result cancel(@RequestBody OrderDTO orderDTO){
        String orderSn = orderDTO.getOrderSn();
        orderService.deleteRedis(orderSn);

        Order order = new Order();
        order.setOrderSn(orderSn).setOrderStatus(-1);
        orderService.changeStatus(order);

        return Result.success();
    }

    @GetMapping("getKillPath")
    public Result beforeKill(int userId,int goodsId){
        String key = "Path_"+goodsId+"_"+userId;
        String md5 = MD5Utils.getMD5(key);
        redisUtils.set(key,md5,60L,TimeUnit.SECONDS);

        return Result.success(md5);
    }

    @PostMapping("{path}/addKillOrder")
    @ApiOperation(value = "新增秒杀商品订单", notes = "用户提交秒杀商品订单")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "Order", name = "order", value = "订单信息"),
            @ApiImplicitParam(dataType = "OrderGoods", name = "orderGoods", value = "秒杀商品信息")
    })
    @NoRepeatSubmit
    public Result addKillOrder(@RequestBody OrderDTO orderDTO,@PathVariable("path") String path) throws InterruptedException {

        OrderGoods orderGoods = orderDTO.getOrderGoods();
        if (!redisUtils.exists("KillGoods"+ orderGoods.getGoodsId())) {
            return Result.error("未到商品开售时间");
        }

        String key = "Path_"+orderGoods.getGoodsId()+"_"+orderDTO.getUserId();
        if (!redisUtils.exists(key)){
            return Result.error("请重试");
        }
        String md5 = (String) redisUtils.get(key);
        if (!path.equals(md5)) return Result.error("请重试");


        //获取秒杀商品的锁 若获取不到重复获取10秒，且获取到了只允许操作30秒 30秒后自动解锁
        RLock lock = redissonClient.getFairLock("key"+orderGoods.getGoodsId());
        boolean tryLock = lock.tryLock(30, 10, TimeUnit.SECONDS);
        if (tryLock) {
            try {
                orderService.addKillOrder(orderDTO);
            } finally {
                lock.unlock();
            }
        }

        return Result.success(orderDTO.getOrder().getOrderSn());
    }

    @PostMapping("confirmKill")
    @ApiOperation(value = "确认购买秒杀商品", notes = "根据orderSn将订单状态修改为待评价")
    @ApiImplicitParam(dataType = "String", name = "orderSn", value = "订单编号")
    @Transactional
    public Result confirmKill(@RequestBody OrderDTO orderDTO){
        String orderSn = orderDTO.getOrderSn();

        Order order = new Order();
        order.setOrderSn(orderSn).setOrderStatus(1);
        //修改订单状态为待评价
        orderService.changeStatus(order);

        redisUtils.del("OOTKillOrder:"+orderSn);
        orderService.deleteRedis(orderSn);

        //修改库存表
        int orderId = orderService.getOrderId(orderSn);
        List<OrderGoods> orderGoodsList = orderGoodsService.getOrderGoods(orderId);
        for (OrderGoods orderGoods : orderGoodsList) {
            killStockService.lockToSale(orderGoods);
            goodsService.dealCountChange(orderGoods.getGoodsId(),orderGoods.getGoodsNum());
        }

        return Result.success();
    }


}
